iT邦幫忙

2026 iThome 鐵人賽

DAY 30
0

之前的StudySession可以透過方法增加分鐘,但外部仍然能直接寫session.minutes = -100。這會繞過原本希望使用的方法,也可能讓物件保存不合理的資料。

物件導向中的封裝,是把資料和操作資料的方法放在一起,並限制外部只能透過允許的方式修改內容。JavaScript類別可以使用#開頭的私有欄位,下面將私有資料、修改方法和讀取方式都放進同一個類別:


class StudySession {
  #minutes = 0;

  constructor(topic, goalMinutes = 60) {
    this.topic = topic;
    this.goalMinutes = goalMinutes;
  }

  addMinutes(minutes) {
    if (typeof minutes !== "number" || minutes <= 0) {
      throw new RangeError("分鐘必須是大於 0 的數字");
    }

    this.#minutes += minutes;
  }

  get minutes() {
    return this.#minutes;
  }

  get isComplete() {
    return this.#minutes >= this.goalMinutes;
  }
}

#minutes屬於每一個StudySession實例,但只能在這個類別內使用。在類別外寫session.#minutes會直接出現語法錯誤,因此外部不能跳過類別提供的方法任意修改。

addMinutes()讓所有分鐘變更都先經過同一個檢查,只要外部都透過這個方法操作,就能避免負數或錯誤型別被加入。

私有欄位不能直接從外部讀取。如果希望外部可以查看結果,但不能直接修改,可以提供minutes和isComplete兩個 getter。

getter使用時看起來像屬性,不需要加小括號:

console.log(session.minutes);
console.log(session.isComplete);

https://ithelp.ithome.com.tw/upload/images/20261014/20178696TaIkPCaofM.png

這裡和作用域篇章看起來一樣都有「外部不能取得」的效果,但原因不同。作用域是依照變數宣告的位置,決定一個變數名稱能在哪個函式或區塊中使用;私有欄位則是類別提供的存取限制,每個實例都有自己的#minutes,只有這個類別的方法能操作它。

簡單來說,作用域處理的是變數在哪裡可見,封裝處理的是物件允許外部怎麼使用資料。兩者都能避免資料被隨意操作,但用途與規則並不相同。


上一篇
Day29 export
系列文
從頭開始的Javascript學習之旅 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言